<!-- 同步布局编辑 -->
<template>
  <container-wrapper :designer="designer"
    :widget="widget"
    :parent-widget="parentWidget"
    :parent-list="parentList"
    :index-of-parent-list="indexOfParentList">
    <div :key="widget.id"
      class="layout-container"
      @click.stop="selectWidget(widget)"
      :style="{width: widget.options.cardWidth + '!important' || ''}"
      :class="[selected ? 'selected' : '', customClass]">
      <el-container :class="ns.b()"
        :style="{ padding: '8px', background: '#fff', paddingTop:'8px','min-height': `${minHeight-10}px`,height:'100%' }">
        <el-container style="position: relative">
          <div :class="ns.b('content')">
            <div :class="ns.b('aside')"
              v-show="isAside==true && setAside==true"
              :style="{ '--var-aside-width': planWidth }">
              <el-aside :class="ns.b('main-aside')"
                :style="{ width: planWidth }">
                <draggable :list="widget.leftLists"
                  item-key="id"
                  :group="{ name: 'dragGroup', pull: 'clone', put: true }"
                  :clone="handleClone"
                  handle=".drag-handler"
                  tag="transition-group"
                  :component-data="{name: 'fade'}"
                  ghost-class="ghost"
                  :animation="200"
                  :sort="true"
                  @end="(evt) => onContainerDragEnd(evt, widget.leftLists)"
                  @add="(evt) => onContainerDragAdd(evt, widget.leftLists)"
                  @update="onContainerDragUpdate"
                  :move="checkContainerMove">
                  <template #item="{ element: subWidget, index: swIdx }">
                    <div :class="[
                        'layout-edit-padding',
                        'form-widget-list',
                        widgetFullHeightClass(subWidget.type, 'aside')
                      ]">
                      <template v-if="'container' === subWidget.category">
                        <component :is="subWidget.type + '-widget'"
                          :widget="subWidget"
                          :designer="designer"
                          :key="subWidget.id"
                          :parent-list="widget.leftLists"
                          :index-of-parent-list="swIdx"
                          :parent-widget="widget"></component>
                      </template>
                      <template v-else>
                        <component :is="subWidget.type + '-widget'"
                          :field="subWidget"
                          :designer="designer"
                          :key="subWidget.id"
                          :parent-list="widget.leftLists"
                          :index-of-parent-list="swIdx"
                          :parent-widget="widget"
                          :design-state="true"></component>
                      </template>
                    </div>
                  </template>
                </draggable>
              </el-aside>
              <div ref="asideBlockRef"
                :class="ns.be('aside', 'line')"
                @click.stop.prevent="onLineClick"
                @mousedown.stop.prevent="planMousedDown"
                @mouseup.stop.prevent="planMouseUp">
                <el-icon v-if="showAside">
                  <arrow-left />
                </el-icon>
                <el-icon v-else>
                  <arrow-right />
                </el-icon>
              </div>
            </div>
            <el-container :style="finalMainStyle">
              <el-main :class="ns.b('main-content')"
                :style="{ height:'100%' }">
                <draggable :list="widget.rightLists"
                  item-key="id"
                  :group="{ name: 'dragGroup', pull: true, put: true }"
                  handle=".drag-handler"
                  tag="transition-group"
                  :component-data="{name: 'fade'}"
                  ghost-class="ghost"
                  :animation="200"
                  :sort="true"
                  @end="(evt) => onContainerDragEnd(evt, widget.rightLists)"
                  @add="(evt) => onContainerDragAdd(evt, widget.rightLists)"
                  @update="onContainerDragUpdate"
                  :move="checkContainerMove">
                  <template #item="{ element: subWidget, index: swIdx }">
                    <div :class="[
                        'layout-edit-padding',
                        'form-widget-list',
                        widgetFullHeightClass(subWidget.type, 'content')
                      ]">
                      <template v-if="'container' === subWidget.category">
                        <component :is="subWidget.type + '-widget'"
                          :widget="subWidget"
                          :designer="designer"
                          :key="subWidget.id"
                          :parent-list="widget.rightLists"
                          :index-of-parent-list="swIdx"
                          :parent-widget="widget"></component>
                      </template>
                      <template v-else>
                        <component :is="subWidget.type + '-widget'"
                          :field="subWidget"
                          :designer="designer"
                          :key="subWidget.id"
                          :parent-list="widget.rightLists"
                          :index-of-parent-list="swIdx"
                          :parent-widget="widget"
                          :design-state="true"></component>
                      </template>
                    </div>
                  </template>
                </draggable>
              </el-main>
            </el-container>
          </div>
        </el-container>
        <div v-if="isMove"
          :class="ns.b('panel-mask')"
          @mouseup.stop="planMouseUp"
          @mousemove.stop="planMouseMove"></div>
      </el-container>
    </div>
  </container-wrapper>
</template>

<script>
import { useNamespace } from 'element-plus';
import i18n from "@/utils/i18n"
import containerMixin from "@/components/form-designer/form-widget/container-widget/containerMixin"
import ContainerWrapper from "@/components/form-designer/form-widget/container-widget/container-wrapper"
import FieldComponents from '@/components/form-designer/form-widget/field-widget/index'
import refMixinDesign from "@/components/form-designer/refMixinDesign"
import { ArrowDown, ArrowUp, ArrowRight, ArrowLeft } from '@element-plus/icons-vue'

export default {
  name: "layout-sync-widget",
  componentName: 'ContainerWidget',
  mixins: [i18n, containerMixin, refMixinDesign],
  inject: ['refList', 'setLeftAsideHidden', 'setRightAsideHidden', 'getLeftAsideHidden', 'getRightAsideHidden'],
  components: {
    ContainerWrapper,
    ...FieldComponents,
    ArrowDown,
    ArrowUp,
    ArrowRight,
    ArrowLeft
  },
  props: {
    field: Object,
    widget: Object,
    parentWidget: Object,
    parentList: Array,
    indexOfParentList: Number,
    designer: Object,
    designState: {
      type: Boolean,
      default: false
    },
    mainStyle: {
      type: Object,
      default: null
    },
    minHeight: { type: Number },
  },
  data() {
    return {
      ns: useNamespace('layout', 'rk'),
      showAside: true,
      asideBlockRef: null,
      planBasicWidth: '700px',
      planWidth: '700px',
      tempWidth: '700px',
      isMove: false,
      moving: false,
      setAside: true,
      // 保存左侧列表的副本，用于拖拽时恢复
      leftListsBackup: []
    }
  },
  computed: {
    selected() {
      return this.widget.id === this.designer.selectedId
    },
    customClass() {
      return this.widget.options.customClass || 'full-height'
    },
    finalMainStyle() {
      let finalStyle = {
        border: '1px solid #dadada',
        width: '50%'
      }
      if (this.mainStyle) {
        finalStyle = { ...finalStyle, ...this.mainStyle }
      }
      return finalStyle
    },
    isAside() {
      return !this.widget.options.leftRightLayoutAsideHide
    },
  },
  created() {
    // 为左右两侧元素添加位置标识
    this.markLayoutElements();
    // 创建左侧列表的备份
    this.createLeftListsBackup();
  },
  mounted() {
    this.initWindowSize();
    this.asideHidden();
    this.hideMainPanels();
  },
  updated() {
    // 每次组件更新后重新标记左右两侧元素位置
    this.markLayoutElements();
  },
  methods: {
    // 添加专门的克隆处理函数
    handleClone(original) {
      return this.deepCloneComponent(original);
    },

    /**
     * 为左右两侧的元素添加位置标识
     * 左侧标记为'left'，右侧标记为'right'
     */
    markLayoutElements() {
      // 标记左侧元素
      this.markElements(this.widget.leftLists, 'left');
      
      // 标记右侧元素
      this.markElements(this.widget.rightLists, 'right');
    },

    /**
     * 递归标记元素位置
     * @param {Array} items - 要标记的元素列表
     * @param {String} position - 位置标识('left'或'right')
     */
    markElements(items, position) {
      if (!items || !Array.isArray(items)) return;

      items.forEach((item, index) => {
        if (item) {
          // 为每个元素添加位置标识
          item._layoutPosition = position;
          // 递归标记嵌套元素
          if (item.category === 'container') {
            // 特别处理 grid 容器
            if (item.type === 'grid' && item.cols && Array.isArray(item.cols)) {
              item.cols.forEach((col, colIndex) => {
                // 为grid-col组件本身添加位置标识
                col._layoutPosition = position;
                if (col.widgetList && Array.isArray(col.widgetList)) {
                  this.markElements(col.widgetList, position);
                }
              });
            }

            // 特别处理 tab 容器
            if (item.type === 'tab' && item.tabs && Array.isArray(item.tabs)) {
              item.tabs.forEach((tab, tabIndex) => {
                if (tab.widgetList && Array.isArray(tab.widgetList)) {
                  this.markElements(tab.widgetList, position);
                }
              });
            }

            // 特别处理 grid-col 容器（直接在容器中的grid-col）
            if (item.type === 'grid-col' && item.widgetList && Array.isArray(item.widgetList)) {
              // 为grid-col组件本身添加位置标识
              item._layoutPosition = position;
              this.markElements(item.widgetList, position);
            }

            // 处理其他容器的 widgetList
            if (item.widgetList && Array.isArray(item.widgetList) &&
              item.type !== 'grid' && item.type !== 'tab' && item.type !== 'grid-col') {
              this.markElements(item.widgetList, position);
            }

            // 处理特殊容器如左右布局等
            if (item.leftLists && Array.isArray(item.leftLists)) {
              this.markElements(item.leftLists, 'left');
            }
            if (item.rightLists && Array.isArray(item.rightLists)) {
              this.markElements(item.rightLists, 'right');
            }
          }
        }
      });
    },

    /**
     * 隐藏主界面的左右面板
     */
    hideMainPanels() {
      if (this.setLeftAsideHidden) {
        this.setLeftAsideHidden(true);
      }
      if (this.setRightAsideHidden) {
        this.setRightAsideHidden(true);
      }
    },

    /**
     * 提供给外部调用的方法
     * 控制表单侧边显示隐藏
     */
    asideHidden() {
    },

    /**
     * 提供给外部调用的方法
     * 控制侧边显示隐藏
     * @param {Boolean} state 状态
     */
    setAsdieHidden(state) {
      this.setAside = !state
    },

    /**
     * 创建左侧列表的备份
     */
    createLeftListsBackup() {
      // 清空现有备份
      this.leftListsBackup.splice(0, this.leftListsBackup.length);

      // 创建新的备份
      if (this.widget.leftLists && Array.isArray(this.widget.leftLists)) {
        this.widget.leftLists.forEach(item => {
          this.leftListsBackup.push(JSON.parse(JSON.stringify(item)));
        });
      }
    },

    // 修改恢复列表函数
    restoreLeftLists() {
      // 恢复左侧列表
      this.widget.leftLists.splice(0, this.widget.leftLists.length);

      this.leftListsBackup.forEach(item => {
        this.widget.leftLists.push(JSON.parse(JSON.stringify(item)));
      });
      this.markLayoutElements();
    },

    // 修改拖拽结束处理函数
    onContainerDragEnd(evt, list) {
      // 如果是从左侧拖拽，恢复左侧列表
      if (list === this.widget.leftLists) {
        // 直接调用恢复方法，不使用nextTick
        this.restoreLeftLists();
      } else {
      }
    },

    // 重构判断函数，确保能正确识别来自左侧列表的元素（包括嵌套在grid-col中的元素）
    isElementFromLeftList(element) {
      // 首先检查元素本身是否带有 _isFromLeft 标识
      if (element && element.hasOwnProperty('_isFromLeft') && element._isFromLeft === true) {
        return true;
      }

      // 增加对_dragSource标记的检查
      if (element && element.hasOwnProperty('_dragSource') && element._dragSource === 'left') {
        return true;
      }

      // 检查是否是容器组件且包含来自左侧的嵌套元素
      if (element && element.category === 'container') {
        let hasLeftElement = false;

        // 处理 grid 容器
        if (element.type === 'grid' && element.cols && Array.isArray(element.cols)) {
          for (let col of element.cols) {
            if (col && col.widgetList && Array.isArray(col.widgetList)) {
              for (let widget of col.widgetList) {
                if (this.isElementFromLeftList(widget)) {
                  hasLeftElement = true;
                  break;
                }
              }
            }
            if (hasLeftElement) break;
          }
        }

        // 处理 tab 容器
        if (element.type === 'tab' && element.tabs && Array.isArray(element.tabs)) {
          for (let tab of element.tabs) {
            if (tab && tab.widgetList && Array.isArray(tab.widgetList)) {
              for (let widget of tab.widgetList) {
                if (this.isElementFromLeftList(widget)) {
                  hasLeftElement = true;
                  break;
                }
              }
            }
            if (hasLeftElement) break;
          }
        }

        // 特别处理 grid-col 容器
        if (element.type === 'grid-col' && element.widgetList && Array.isArray(element.widgetList)) {
          for (let widget of element.widgetList) {
            if (this.isElementFromLeftList(widget)) {
              hasLeftElement = true;
              break;
            }
          }
        }

        // 处理其他容器的 widgetList
        if (element.widgetList && Array.isArray(element.widgetList) &&
          element.type !== 'grid' && element.type !== 'tab' && element.type !== 'grid-col') {
          for (let widget of element.widgetList) {
            if (this.isElementFromLeftList(widget)) {
              hasLeftElement = true;
              break;
            }
          }
        }

        // 处理自定义容器组件，如左右布局等
        if (element.leftLists && Array.isArray(element.leftLists) && !hasLeftElement) {
          for (let widget of element.leftLists) {
            if (this.isElementFromLeftList(widget)) {
              hasLeftElement = true;
              break;
            }
          }
        }
        if (element.rightLists && Array.isArray(element.rightLists) && !hasLeftElement) {
          for (let widget of element.rightLists) {
            if (this.isElementFromLeftList(widget)) {
              hasLeftElement = true;
              break;
            }
          }
        }

        return hasLeftElement;
      }

      return false;
    },

    /**
     * 检查接收哪些组件拖放，控制拖拽行为
     * @param evt 拖拽事件
     * @returns {boolean}
     */
    checkContainerMove(evt) {
      // 获取拖拽目标元素
      const targetElement = evt.to;

      // 查找最近的祖先节点中是否有来自左侧列表的容器
      let parent = targetElement.parentElement;
      while (parent) {
        // 如果找到了 .el-aside，则说明目标在左侧区域
        if (parent.classList.contains('el-aside')) {
          return false;
        }
        // 可以进一步判断是否有自定义属性标记为左侧区域
        // 例如：通过 data-side="left" 或特定 class
        parent = parent.parentElement;
      }

      // 额外防护：检查是否试图拖入左侧 lists 中
      const dragGroup = evt.from?.__vue__?.$parent?.$options?.name;
      if (dragGroup === 'tab-pane' || dragGroup === 'grid-col') {
        // 检查父链中是否属于 leftLists
        let currentList = this.getParentList(evt.to);
        while (currentList) {
          if (currentList === this.widget.leftLists) {
            return false;
          }
          currentList = this.getParentList(currentList);
        }
      }
      return true;
    },

    /**
     * 获取指定元素所属的父级列表
     * @param el DOM元素
     * @returns {Array|null}
     */
    getParentList(el) {
      const vueInstance = el.__vue__;
      if (vueInstance && Array.isArray(vueInstance.parentList)) {
        return vueInstance.parentList;
      }
      return null;
    },
    // 重构深度克隆函数，确保所有嵌套元素都被正确克隆并分配唯一ID
    deepCloneComponent(original) {
      if (!original) return original;

      // 深度克隆组件
      const cloned = JSON.parse(JSON.stringify(original));

      // 生成新的唯一ID
      const generateNewId = () => {
        return 'widget' + Math.random().toString(36).substring(2, 10) + Date.now().toString(36);
      };

      // 递归处理所有嵌套组件的ID
      const processWidgetIds = (widget) => {
        if (!widget) return;

        // 为当前组件生成新ID
        widget.id = generateNewId();

        if (widget.guid) {
          widget.guid = generateNewId().toUpperCase();
        }
        // 递归处理容器组件的子组件
        if (widget.category === 'container') {
          // 处理 grid 容器
          if (widget.type === 'grid' && widget.cols && Array.isArray(widget.cols)) {
            widget.cols.forEach((col) => {
              if (col) {
                col.id = generateNewId();

                if (col.guid) {
                  col.guid = generateNewId().toUpperCase();
                }
                // 递归处理 grid-col 内部的 widgetList
                if (col.widgetList && Array.isArray(col.widgetList)) {
                  col.widgetList.forEach(processWidgetIds);
                }
              }
            });
          }

          // 处理 tab 容器
          if (widget.type === 'tab' && widget.tabs && Array.isArray(widget.tabs)) {
            widget.tabs.forEach((tab) => {
              if (tab) {
                tab.id = generateNewId();
                if (tab.guid) {
                  tab.guid = generateNewId().toUpperCase();
                }
                // 递归处理 tab 内部的 widgetList
                if (tab.widgetList && Array.isArray(tab.widgetList)) {
                  tab.widgetList.forEach(processWidgetIds);
                }
              }
            });
          }

          // 特别处理 grid-col 容器
          if (widget.type === 'grid-col' && widget.widgetList && Array.isArray(widget.widgetList)) {
            widget.widgetList.forEach(processWidgetIds);
          }

          // 处理其他容器的 widgetList
          if (widget.widgetList && Array.isArray(widget.widgetList) &&
            widget.type !== 'grid' && widget.type !== 'tab' && widget.type !== 'grid-col') {
            widget.widgetList.forEach(processWidgetIds);
          }

          // 处理自定义容器组件，如左右布局等
          if (widget.leftLists && Array.isArray(widget.leftLists)) {
            widget.leftLists.forEach(processWidgetIds);
          }
          if (widget.rightLists && Array.isArray(widget.rightLists)) {
            widget.rightLists.forEach(processWidgetIds);
          }
        }
      };

      // 处理克隆后的组件及其所有嵌套组件的ID
      processWidgetIds(cloned);
      return cloned;
    },

    // 拖拽添加处理函数
    onContainerDragAdd(evt, targetList) {
      const { newIndex } = evt;
      if (newIndex == null || !targetList[newIndex]) return;

      const item = targetList[newIndex];

      // 若拖入左侧列表，则禁止操作并移除元素
      if (targetList === this.widget.leftLists) {
        targetList.splice(newIndex, 1);
        return;
      }

      // 检查是否是从左侧列表拖拽到右侧列表
      const isFromLeftToRight = this.isElementFromLeftList(item);

      // 只有从左侧拖拽到右侧时才进行克隆操作
      if (isFromLeftToRight) {
        const clonedItem = this.deepCloneComponent(item);
        // 克隆的组件不应该带有 _isFromLeft 标识
        if (clonedItem && clonedItem.hasOwnProperty('_isFromLeft')) {
          delete clonedItem._isFromLeft;
        }
        // 克隆的组件应该标记为右侧组件
        if (clonedItem) {
          clonedItem._dragSource = 'right';
        }
        targetList[newIndex] = clonedItem;
      } else {
        // 右侧内部拖拽时，确保元素不带 _isFromLeft 标识
        if (item && item.hasOwnProperty('_isFromLeft')) {
          delete item._isFromLeft;
        }
        // 确保右侧元素标记为右侧组件
        if (item) {
          item._dragSource = 'right';
        }
      }

      // 触发历史变更事件
      this.designer.emitHistoryChange();
    },

    /**
     * 鼠标松开
     * @param e event
     */
    planMouseUp(e) {
      this.isMove = false;
      this.planBasicWidth = this.planWidth;
      setTimeout(() => {
        this.moving = false;
      }, 100);
    },

    /**
     * 拖动改变面板大小
     */
    planMousedDown() {
      return this.isMove = true;
    },

    /**
     * 鼠标移动
     * @param e event
     */
    planMouseMove(e) {
      if (this.isMove && this.showAside) {
        this.moving = true;
        this.planWidth = `${e.layerX}px`;
        this.tempWidth = `${e.layerX}px`;
      }
    },

    /**
     * 设置宽度
     * @param width 宽度
     */
    setWidth(width) {
      this.planWidth = width;
      this.tempWidth = width;
      this.planBasicWidth = width;
    },

    onLineClick() {
      if (!this.moving) {
        this.showAside = !this.showAside;
        if (this.showAside) {
          this.planWidth = this.tempWidth;
          this.planBasicWidth = this.tempWidth;
        } else {
          this.planWidth = '0px';
        }
      }
    },

    initWindowSize() {
      this.setWidth('700px')
    },

    /**
     * 获取部件的撑满高度的样式类
     * @param {String} type 部件类型
     * @returns {String} 样式类
     */
    widgetFullHeightClass(type) {
      return ['zoning-unit-tree', 'data-table'].includes(type) ? 'widget-full-hight' : ''
    }
  }
}
</script>

<style lang="scss" scoped>
@import "@/styles/function.scss";

.layout-container.selected {
  outline: 2px solid $--color-primary !important;
}
.layout-container {
  outline: 2px solid #d9d9d9;
  height: 100% !important;
  margin: 2px;

  .form-widget-list {
    min-height: 28px;
    box-sizing: border-box;
  }
  .widget-full-hight {
    height: 100% !important;
  }
}

@include b(layout) {
  height: 100% !important;
  width: 100%;
  position: relative;
  .layout-edit-padding {
    padding: 5px;
  }

  &-panel-mask {
    position: absolute;
    top: 0;
    width: 100%;
    height: 100%;
    background-color: #ffffff;
    opacity: 0.3;
    z-index: 80;
  }

  &-header {
    display: flex;
  }

  &-header-group {
    display: flex;
    align-content: center;
    align-items: center;
    width: 100%;

    &__left {
      // width: 50%;
      box-sizing: border-box;
      height: 100%;
    }

    &__right {
      // width: 50%;
      margin-left: auto;
      box-sizing: border-box;
      height: 100%;
    }
  }

  &-header-left {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  &-left-g {
    width: 90%;
    display: flex;
    justify-content: flex-start;
  }

  &-header-right {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  &-right-g {
    width: 90%;
    display: flex;
    justify-content: flex-end;
  }

  &-aside {
    height: 100%;
    //background-color: #0d84ff;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    margin-right: 10px;

    &__body {
      box-sizing: border-box;
      border: 1px solid #dadada;
    }

    &__line {
      position: absolute;
      top: 0;
      width: 10px;
      left: var(--var-aside-width);
      height: 100%;
      cursor: w-resize;
      z-index: 90;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    &__line:hover {
      background-color: #eaeaea;
    }
  }

  &-content {
    position: absolute;
    top: 0;
    width: 100%;
    height: 100%;
    display: flex;
  }

  &-main-content {
    //background-color: #e7746f;
    box-sizing: border-box;
    padding: 0;
    margin: 0;
    overflow-y: auto;
    flex-direction: column;
  }

  &-main-footer {
    //background-color: #f8f38b;
    box-sizing: border-box;
    border: 1px solid #dadada;
    border-left: unset;
    border-right: unset;
    border-bottom: unset;
    padding: 0;
    margin: 0;
  }

  &-ex-text-center {
    text-align: center;
    font-size: 35px;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
  }
}
</style>